#include "w25q.h"

void W25Q_WriteBytes(uint8_t* data, uint8_t num)
{
	HAL_SPI_Transmit_DMA(&hspi1, data, num);
}

void W25Q_ReadBytes(uint8_t *data, uint8_t num)
{
	HAL_SPI_Receive_DMA(&hspi1, data, num);
}

uint8_t W25Q_ReadWrite(uint8_t tx_data)
{
	uint8_t rx_data;
	HAL_SPI_TransmitReceive_DMA(&hspi1, &tx_data, &rx_data, 1);
	return rx_data;
}



uint16_t W25Q_ReadDevId(void)
{
	uint16_t result = 0;
	uint8_t mId;
	uint8_t devId;
	
	W25Q_CS_0;
	W25Q_ReadWrite(0x90);
	W25Q_ReadWrite(0);
	W25Q_ReadWrite(0);
	W25Q_ReadWrite(0);
	
	mId = W25Q_ReadWrite(0);
	devId = W25Q_ReadWrite(0);
	W25Q_CS_1;
	result = mId;
	result <<= 8;
	result |= devId;
	return result;
}

uint8_t Read_Status_Register(uint8_t cmd)
{
	uint8_t result = 0;
	W25Q_CS_0;
	
	switch(cmd) {
		case 1:
			W25Q_ReadWrite(W25Q_READ_STATUS_REG1);
		break;
		case 2:
			W25Q_ReadWrite(W25Q_READ_STATUS_REG2);
		break;
		case 3:
			W25Q_ReadWrite(W25Q_READ_STATUS_REG3);
		break;
	}
	result = W25Q_ReadWrite(0);
	W25Q_CS_1;
	return result;
}

void W25Q_WriteEnable()
{
	W25Q_CS_0;
	W25Q_ReadWrite(W25Q_WRITE_ENABLE);
	W25Q_CS_1;
}

void W25Q_WriteDisable()
{
	W25Q_CS_0;
	W25Q_ReadWrite(W25Q_WRITE_DISABLE);
	W25Q_CS_1;
}

void W25Q_Chip_Erase() 
{
	W25Q_WriteEnable();
	HAL_Delay(3);
	W25Q_CS_0;
	W25Q_ReadWrite(W25Q_CHIP_ERASE);
	W25Q_CS_1;
}

void W25Q_Wait_Busy()
{
	while((Read_Status_Register(1) & 0x01) == 0x01)
	{}
}

void W25Q_Page_Write(uint32_t addr, uint8_t* pBuf, uint16_t num)
{
	W25Q_WriteEnable();
	HAL_Delay(3);
	W25Q_CS_0;
	W25Q_ReadWrite(W25Q_PAGE_WRITE);
	
	W25Q_ReadWrite( (uint8_t)(addr >> 16));
	W25Q_ReadWrite( (uint8_t)(addr >> 8));
	W25Q_ReadWrite( (uint8_t) addr);

	W25Q_WriteBytes(pBuf, num);
	//TODO  waiting for spi tx done
	while(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_BUSY_TX)
	{}	
	W25Q_CS_1;
	W25Q_Wait_Busy();
}

void W25Q_Page_Read(uint32_t addr, uint8_t* pBuf, uint16_t num)
{
	W25Q_CS_0;
	W25Q_ReadWrite(W25Q_PAGE_READ);
	W25Q_ReadWrite( (uint8_t)(addr >> 16));
	W25Q_ReadWrite( (uint8_t)(addr >> 8));
	W25Q_ReadWrite( (uint8_t) addr);
	
	W25Q_ReadBytes(pBuf, num);
	//TODO  waiting for spi rx done
	while(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_BUSY_RX)
	{}	
	W25Q_CS_1;
}


uint16_t DevId = 0;
uint8_t readReg = 0;
void W25Q_Init() 
{
	DevId = W25Q_ReadDevId();
	if(DevId == 0xEF17) {
		readReg = Read_Status_Register(1);
		readReg = Read_Status_Register(2);
		readReg = Read_Status_Register(3);
	}
}


